package com.gmrz.uas.plugin.idauth;

import com.gmrz.uas.plugin.authservice.AuthServiceConfigSpec;
import com.gmrz.uas.plugin.authservice.AuthServiceData;
import com.gmrz.uas.plugin.authservice.BaseAuthServicePlugin;
import com.gmrz.uas.plugin.authservice.exception.AuthenticationException;
import com.gmrz.uas.plugin.exception.PluginException;
import com.gmrz.uas.plugin.util.HttpClientUtil;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by gongyuqiang on 2017/5/14.
 */
public class IDAuthService extends BaseAuthServicePlugin {

    private static final Logger LOG = LogManager.getLogger(IDAuthService.class);
    public static final String CONFIG_KEY_APPKEY = "appKey";
    public static final String CONFIG_KEY_SECRET = "appSecret";
    public static final String CONFIG_KEY_SERVER_HOST = "host";
    public static final String CONFIG_KEY_SERVER_PORT = "port";

    public IDAuthService(){
        this.allConfig = new HashMap<String, String>();

        this.allConfigSpec = new HashMap<String, AuthServiceConfigSpec>();
        this.allConfigSpec.put(CONFIG_KEY_APPKEY, new AuthServiceConfigSpec("", ""));
        this.allConfigSpec.put(CONFIG_KEY_SECRET, new AuthServiceConfigSpec("", ""));
        this.allConfigSpec.put(CONFIG_KEY_SERVER_PORT, new AuthServiceConfigSpec("", ""));
        this.allConfigSpec.put(CONFIG_KEY_SERVER_HOST, new AuthServiceConfigSpec("", ""));

    }
    protected  String makeSign(String appKey, String appSecret, String cardno, String name, String clienttime){
        StringBuilder builder = new StringBuilder();
        builder.append(appSecret);
        builder.append("cardNo");
        builder.append(cardno);
        builder.append("clienttime");
        builder.append(clienttime);
        builder.append("methodverify");
        builder.append("name");
        builder.append(name);
        builder.append("userKey");
        builder.append(appKey);
        builder.append(appSecret);
        return CryptoUtil.getMD5Digest(builder.toString());
    }

    protected  String buildPost(String appKey, String name, String cardno, String clienttime, String sign) throws UnsupportedEncodingException {
        StringBuilder builder = new StringBuilder();
        builder.append("userKey=" + URLEncoder.encode(appKey,"UTF-8"));
        builder.append("&clienttime=" + URLEncoder.encode(clienttime, "UTF-8"));
        builder.append("&sign=" + URLEncoder.encode(sign, "UTF-8"));
        builder.append("&name=" + URLEncoder.encode(name, "UTF-8"));
        builder.append("&cardNo=" + URLEncoder.encode(cardno, "UTF-8"));
        builder.append("&method=verify");
        builder.append("&v=1.0");
        return builder.toString();
    }

    /**
     * 实名认证
     * @param userId
     * @param contents
     * @throws PluginException
     */
    public void authenticate(String userId, List<AuthServiceData> contents) throws PluginException {

        if(contents == null || contents.size() == 0)
            throw new AuthenticationException("invalid params for idauth authentication");
        String name = "";
        String cardno = "";
        String startTime = "";
        String endTime = "";

        String appKey = this.allConfig.get(CONFIG_KEY_APPKEY);
        String appSecret = this.allConfig.get(CONFIG_KEY_SECRET);

        //appKey ="36d8bae1844845e5b60f0d7f366671bd";
        //appSecret = "JMipcXBhK6bOnrHWF97M1XZt";

        for(AuthServiceData content: contents){
            if(content.getId() != null && content.getId().equals("cardname")
                    && content.getContent() != null){

                name = new String(content.getContent());
            }
            else if(content.getId() != null && content.getId().equals("cardno")
                    && content.getContent() != null){
                cardno = new String(content.getContent());
            }
            else if(content.getId() != null && content.getId().equals("starttime")
                    && content.getContent() != null){
                startTime = new String(content.getContent());
            }
            else if(content.getId() != null && content.getId().equals("endtime")
                    && content.getContent() != null){
                endTime = new String(content.getContent());
            }
        }

        if(cardno.length() == 0)
            throw new AuthenticationException("invalid params for idauth authentication");
        if(name.length() == 0)
            throw new AuthenticationException("invalid params for idauth authentication");
        if(startTime.length() == 0)
            throw new AuthenticationException("invalid params for idauth authentication");
        if(endTime.length() == 0)
            throw new AuthenticationException("invalid params for idauth authentication");

        name = new sun.misc.BASE64Encoder().encode(CryptoUtil.encrypt3DES(name.getBytes(), appSecret)) ;
        cardno = new sun.misc.BASE64Encoder().encode(CryptoUtil.encrypt3DES(cardno.getBytes(), appSecret)) ;
        startTime = new sun.misc.BASE64Encoder().encode(CryptoUtil.encrypt3DES(startTime.getBytes(), appSecret)) ;
        endTime = new sun.misc.BASE64Encoder().encode(CryptoUtil.encrypt3DES(endTime.getBytes(), appSecret)) ;

        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String clienttime = formatter.format(currentTime);


        String tranNo= UUID.randomUUID().toString().replace("-","");

        Map<String,String> obj = new HashMap<String,String> ();
        obj.put("appKey", appKey);
        obj.put("cardNo", cardno);
        obj.put("name", name);
        obj.put("startTime", startTime);
        obj.put("endTime", endTime);
        obj.put("productType", "01");
        obj.put("industrType", "01");
        obj.put("transactionNo", tranNo);
        obj.put("clientTime", clienttime);

        String signValue = CryptoUtil.sign(obj,appSecret);

        obj.put("sign", signValue);
        Gson gson = new Gson();
        String jsonStr = gson.toJson(obj);


        String host = this.allConfig.get(CONFIG_KEY_SERVER_HOST);
        String port = this.allConfig.get(CONFIG_KEY_SERVER_PORT);

        //host = "192.168.6.134";
        //port = "7031";

        String postUrl = String.format("http://%s:%s/realname-service/v1.0/service/realname", host, port);
        try {
            String response = HttpClientUtil.post(postUrl, jsonStr, "application/json;charset=UTF-8");
            LOG.info("response=" + response);
//            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//            DocumentBuilder db = factory.newDocumentBuilder();
//            Document doc = db.parse(new InputSource(new StringReader(response)));
//            Element root =  doc.getDocumentElement();
//
//            if(!root.getTagName().equals("Response")){
//                throw new AuthenticationException("idauth Authentication failed");
//            }
//
//            int result = 1;
//            for(int i = 0; i < root.getChildNodes().getLength(); i++){
//                Node node = root.getChildNodes().item(i);
//                if(node.getNodeName().equals("result")){
//                    result = Integer.parseInt(node.getTextContent());
//                }
//            }
            JsonObject resultJson = (new JsonParser()).parse(response).getAsJsonObject();
            int code = resultJson.get("code").getAsInt();
            if(code != 0){
                throw new AuthenticationException("idauth Authentication failed");
            }
            int result = resultJson.get("result").getAsInt();
            if(code != 0){
                throw new AuthenticationException("idauth Authentication failed");
            }
            if(result != 0){
                throw new AuthenticationException("idauth Authentication failed");
            }
        }
        catch (AuthenticationException e){
            LOG.error(e);
            throw e;
        }
        catch (Exception e){
            throw new AuthenticationException("idauth Authentication failed");
        }
    }

    @Override
    public void unregister(String userId) throws PluginException {

    }
}
